//
// Created by 覃州 on 2024/4/8.
//

#include "config.h"
#include <list>

namespace canon {

Config::ConfigVarMap Config::s_datas{};

ConfigVarBase::ptr Config::LookupBase(const std::string &name)
{
    auto it = s_datas.find(name);
    return it == s_datas.end() ? nullptr : it->second;
}

static void ListAllMember(const std::string &prefix, const YAML::Node &node,
                          std::list<std::pair<std::string, const YAML::Node>> &output)
{
    if (prefix.find_first_not_of("abcdefghikjlmnopqrstuvwxyz._012345678") != std::string::npos) {
        CANON_LOG_INFO(CANON_LOG_ROOT()) << "Config invalid name: " << prefix << " : " << node;
        return;
    }
    output.emplace_back(prefix, node);
    if (node.IsMap()) {
        auto map = node.as<std::map<std::string, YAML::Node>>();
        for (auto &it : map) {
            ListAllMember(prefix.empty() ? it.first : prefix + "." + it.first, it.second, output);
        }
    }
    std::cout << "";
}

void Config::LoadFromYaml(const YAML::Node &root)
{
    std::list<std::pair<std::string, const YAML::Node>> all_nodes;
    ListAllMember("", root, all_nodes);
    for (auto &node : all_nodes) {
        std::string key = node.first;

        if (key.empty()) {
            continue;
        }
        std::transform(key.begin(), key.end(), key.begin(), ::tolower);
        ConfigVarBase::ptr var = LookupBase(key);

        if (var) {
            if (node.second.IsScalar()) {
                var->fromString(node.second.Scalar());
            } else {
                std::stringstream ss;
                ss << node.second;
                var->fromString(ss.str());
            }
        }
    }
}

} // namespace canon
